<template>
  <div v-loading="loading">
    <el-row
      ref="operateList"
      type="flex"
      :justify="justify"
      class="operateList"
      :style="{ 'justify-content': buttonsAlign == 'right' ? 'end' : 'start' }"
    >
      <div  class="tableTitle" style="margin-right: auto;">{{ title || '' }}</div>
      <div v-if="operateList.length !== 0" class="btn-pack">
        <span
          v-for="(item, index) in operateList"
          :key="index"
          class="btn"
          :style="{ 'margin-right': buttonsAlign == 'right' ? '0' : '10px', 'margin-left': buttonsAlign == 'right' ? '10px' : '0'}"
        >
          <lb-render
            v-if="item.render"
            :render="item.render"
            :scope="multipleSelection"
            v-btnAuths="item.auth"
          />
          <el-button
            v-else
            :type="item.type"
            :icon="item.icon"
            :class="item.class"
            @click="handleOperate(item)"
            :disabled="isDisabled(item)"
            v-btnAuths="item.auth"
            v-show="isShow(item)"
          >
            {{ item.name }}
          </el-button>
        </span>
      </div>
      <div class="operateIcon" v-if="isShowTool">
        <el-dropdown
          placement="bottom"
          @command="command"
          size="small"
          trigger="click"
        >
          <span class="el-dropdown-link">
            <i class="el-icon-finished"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item command="medium">{{
              $t("common.loose")
            }}</el-dropdown-item>
            <el-dropdown-item divided command="small">{{
              $t("common.default")
            }}</el-dropdown-item>
            <el-dropdown-item divided command="mini">{{
              $t("common.compact")
            }}</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>

        <el-tooltip
          class="item"
          effect="dark"
          :content="$t('common.refresh')"
          placement="top"
        >
          <i class="el-icon-refresh" @click="getTableData(true)"></i>
        </el-tooltip>
        <el-popover placement="bottom" width="150" trigger="click">
          <config-column
            :column="column"
            :uniqueId="uniqueId"
            @changeColumn="changeColumn"
          ></config-column>
          <i class="el-icon-s-operation" slot="reference"></i>
        </el-popover>
      </div>
    </el-row>
    <div v-if="dataDisplay">
      <lb-table
        v-tableMaxHeight
        :column="selfColumn"
        :data="data"
        :border="border"
        :align="align"
        :pagination="pagination"
        :layout="pageSet"
        :page-sizes="pageSizes"
        :pager-count="pagerCount"
        :current-page.sync="selfCurrentPage"
        :total="total"
        :page-size="selfPageSize"
        v-bind="$attrs"
        v-on="$listeners"
        :height="selfMaxHeight"
        highlight-current-row
        background
        ref="multipleTable"
        @selection-change="handleSelectionChange"
        @size-change="handleSizeChange"
        @p-current-change="handleCurrentChange"
        @sort-change="sortChange"
        @header-dragend="changeTableWidth"
        @row-click="rowClick"
        @select-all="selectAll"
        @select="select"
        :size="size"
        :stripe="true"
      >
      </lb-table>
    </div>
    <el-empty v-else :description="$t('common.noFieldShow')"></el-empty>
  </div>
</template>

<script>
import lbTable from "@/components/lb-table/lb-table";
import lbRender from "@/components/lb-table/lb-render";
import configColumn from "./configColumn";
import { uniqueKey } from "@/utils/judge.js";
export default {
  name: "eleTable",
  components: { lbTable, configColumn, lbRender },
  props: {
    title: {
      type: String,
      default: "",
    },
    buttonsAlign: {
      type: String,
      default: "left",
    },
    isShowTool: {
      type: Boolean,
      default: true,
    },
    // 表格唯一ID，配置列用
    uniqueId: [String, Number],
    // 接口函数是否立即执行
    apiImmediate: {
      type: Boolean,
      default: true,
    },
    align: {
      type: String,
      default: "center",
    },
    // 必须返回一个Promise
    // 列表数据的转化，某些时候请求后的数据不是我们想要的  仅接受一个Promise
    // return { records：Array,total:Number }

    /** 示例
    async transFormdata(data) {
    ////console.log(data);
   1.
    return Promise.resolve({
      records：Array,
      total:Number
    });
    2.
    const list = await 一个异步方法();
    return {records：Array,total:Number };
    },
      */
    // 数据转化函数
    transFormdata: {
      type: Function,
    },
    // 列表接口函数
    getList: {
      type: Function,
    },
    // 请求参数
    formData: {
      type: Object,
      default() {
        return {};
      },
    },
    // 操作列表数组
    operateList: {
      type: Array,
      default() {
        return [];
      },
    },

    // 列数据
    column: {
      type: Array,
      default() {
        return [];
      },
      required: true,
    },
    // 是否有边框
    border: {
      type: Boolean,
      default: true,
    },
    // 是否要分页
    pagination: {
      type: Boolean,
      default: true,
    },
    // 显示分页按钮的个数
    pagerCount: {
      type: Number,
      default: 5,
    },
    // 分页的字段
    pageSet: {
      type: String,
      default: "total, sizes, prev, pager, next, jumper",
    },
    // 页长备选长度
    pageSizes: {
      type: Array,
      default() {
        return [10, 30, 50, 100];
      },
    },
    // // 页长
    pageSize: {
      type: Number,
      default: 10,
    },
    // 按钮组的位置
    justify: {
      type: String,
      default: "start",
    },
    ismock: {
      type: Boolean,
      default: false,
    },
    mockdata: {
      type: Object,
      default: () => {
        return {
          records: [],
          total: 0,
        };
      },
    },
    // 请求之前的钩子
    beforeRequest: Function,
    // 表格最大高度
    maxHeight: Number,
  },
  data() {
    return {
      queryParam: {}, // 请求参数
      selfCurrentPage: 1, // 当前页
      selfPageSize: 10, // 默认每页10条
      data: [], // 表格数据
      total: 0, // 总数
      multipleSelection: [],
      loading: false,
      selfMaxHeight: 0, // 最大高度
      size: "small",
      selfColumn: [],
      field: [], // 排序字段，
      sort: [], // 排序方式，asc正序，desc倒序
      dataDisplay: true,
      selectionAll: false,
    };
  },
  mounted() {
    if (this.apiImmediate && this.getList && !this.ismock) {
      this.getTableData();
    } else {
      if (this.ismock) this.getMockData();
    }
  },
  updated() {
    // ////console.log("更新");
    this.$nextTick(() => {
      this.doLayout();
    });
  },

  computed: {
    // 按钮是否可点击
    isDisabled() {
      return function (item) {
        if (!item.disabled) return false;
        const disabled = item.disabled(this.multipleSelection);
        return disabled;
      };
    },
    // 按钮是否隐藏显示
    isShow() {
      return function (item) {
        const btnAuths = this.$store.getters.btnAuths || [];
        if (!item.auth || btnAuths.includes(item.auth)) {
          if (!item.show) return true;
          const show = item.show(this.multipleSelection);
          return show;
        } else {
          return false;
        }
      };
    },
  },
  methods: {
    // 设置是否已经勾选
    setCheckBool(data, bool) {
      data.checkBool = bool || false;

      let checkStrictly = this.$attrs["checkStrictly"] || false;
      let treeProps = this.$attrs["tree-props"];
      let rowKey = this.$attrs["row-key"];
      if (rowKey && treeProps && !this.$attrs.lazy && checkStrictly) {
        let { children } = treeProps;
        const getList = (obj) => {
          if (obj[children]) {
            obj[children].forEach((val) => {
              if (val[children]) {
                getList(val[children]);
              }
              val.checkBool = bool || false;
            });
          }
          obj.checkBool = bool || false;
        };
        getList(data);
      }
      //console.log(444, data);
    },
    // 树形结构转一维数组
    convertData(data, childrenKey) {
      let rows = [];
      const getList = (obj) => {
        rows.push(obj);
        if (obj[childrenKey]) {
          obj[childrenKey].forEach((val) => {
            if (val[childrenKey]) {
              getList(val[childrenKey]);
            }
            rows.push(val);
          });
        }
      };
      getList(data);
      return rows;
    },
    select(selection, row) {
      this.setCheckBool(row, !row.checkBool);
      //console.log(3, row);
      setTimeout(() => {
        this.subsetSelection();
      }, 0);
    },
    selectAll(selection) {
      this.selectionAll = !this.selectionAll;
      selection.map((ite) => {
        this.setCheckBool(ite, this.selectionAll);
      });
      this.subsetSelection();
    },
    /**
     * @author bing
     * @since 2024-01-03 14:12:46
     *  选择父级自动勾选或取消子集
     */
    subsetSelection() {
      // 非懒加载情况下的树结构
      let checkStrictly = this.$attrs["checkStrictly"] || false;
      let treeProps = this.$attrs["tree-props"];
      let rowKey = this.$attrs["row-key"];
      if (rowKey && treeProps && !this.$attrs.lazy && checkStrictly) {
        try {
          let { children } = treeProps;

          this.multipleSelection.map((ite) => {
            let rows = this.convertData(ite, children);
            //console.log(8888, rows);
            this.$nextTick(() => {
              rows.map((item) => {
                this.$refs["multipleTable"].toggleRowSelection(
                  item,
                  item.checkBool
                );
                // 需要选中并且有子集，展开操作
                //console.log(6, item, item.checkBool);
                if (item.checkBool && item.children && item[children].length) {
                  this.toggleRowExpansion(item, true);
                }
              });
            });
          });
        } catch (error) {
          //console.error("请检查多层级配置项", error);
        }
      }
    },
    // 行点击
    rowClick(row) {
      if (this.$attrs.customRowClick) {
        this.$attrs.customRowClick(row);
        return;
      }
      const selected = this.multipleSelection.some(
        (item) => item.selectId === row.selectId
      );
      if (!selected) {
        this.setCheckBool(row, true);
        this.multipleSelection.push(row);
        this.$refs["multipleTable"].toggleRowSelection(row, true);
      } else {
        this.setCheckBool(row, false);
        var filArr = this.multipleSelection.filter((item) => {
          return item.selectId !== row.selectId;
        });
        this.multipleSelection = filArr; // 取消后剩余选中的
        this.$refs["multipleTable"].toggleRowSelection(row, false);
      }
      this.subsetSelection();
    },
    changeTableWidth() {
      this.$nextTick(() => {
        this.doLayout();
      });
    },
    getMockData() {
      const { records = [], total } = this.mockdata;
      this.data = records.map((ite, index) => {
        return { ...ite, selectId: index };
      });
      this.total = total || 0;
    },
    // 重置列表数据
    resetTableData() {
      this.data = [];
      this.total = 0;
      this.selfCurrentPage = 1;
    },
    getTableData(isReset) {
      if (isReset) {
        this.selfCurrentPage = 1;
      }
      const getParams = {
        pageNum: this.selfCurrentPage,
        pageSize: this.selfPageSize,
        field: this.field.join(","),
        sort: this.sort.join(","),
        ...this.queryParam,
      };
      const data = this.beforeRequest
        ? { ...this.beforeRequest(getParams) }
        : getParams;
      this.loading = true;
      setTimeout(() => {
        this.getList(data)
          .then((res) => {
            if (this.transFormdata) {
              this.transFormdata(res)
                .then((params) => {
                  const { records = [], total } = params;
                  this.data = records.map((ite, index) => {
                    return { ...ite, selectId: index, checkBool: false };
                  });
                  this.total = +total || 0;
                })
                .finally(() => {
                  this.loading = false;
                });
            } else {
              const { records = [], total } = res.data.result;
              this.data = records.map((ite, index) => {
                return { ...ite, selectId: index };
              });
              this.total = +total || 0;
            }
          })
          .finally(() => {
            if (!this.transFormdata) {
              this.loading = false;
            }
            this.changeTableWidth();
          });
      });
    },
    // 点击页码
    handleCurrentChange(val) {
      this.selfCurrentPage = val;
      this.getTableData();
    },
    // 点击每页展示几天数据
    handleSizeChange(val) {
      this.selfCurrentPage = 1;
      this.selfPageSize = val;
      this.getTableData();
    },
    // 按钮事件处理
    handleOperate(item) {
      const data = {
        ...item,
      };
      if (item.isSingle && this.multipleSelection.length != 1) {
        this.$message.error(this.$t("common.single"));
        return;
      }
      if (item.isMultiple && this.multipleSelection.length == 0) {
        this.$message.error(this.$t("common.multiple"));
        return;
      }

      data.rows = JSON.parse(JSON.stringify(this.multipleSelection));

      this.$emit("handleOperateEvent", data);
    },
    // 排序
    sortChange({ column, prop, order }) {
      if (typeof column.sortable === "boolean") return;
      const sort = { ascending: "asc", descending: "desc" };
      const index = this.field.indexOf(prop);
      if (order) {
        // splice
        if (index > -1) {
          this.$set(this.sort, index, sort[order]);
        } else {
          this.field.push(prop);
          this.sort.push(sort[order]);
        }
      } else {
        this.field.splice(index, 1);
        this.sort.splice(index, 1);
      }
      this.getTableData(true);
    },
    handleSelectionChange(rows) {
      //console.log(11111, rows);
      this.multipleSelection = rows;
    },
    clearSelection() {
      this.$refs.multipleTable.clearSelection();
      this.multipleSelection = [];
    },
    // 展开某一行
    toggleRowExpansion(row, selected) {
      this.$refs.multipleTable.toggleRowExpansion(row, selected);
    },
    doLayout() {
      this.$refs.multipleTable.doLayout();
    },
    command(size) {
      this.size = size;
      this.$nextTick(() => {
        this.doLayout();
      });
    },
    // 列改变时触发
    changeColumn(data) {
      this.dataDisplay = data.length > 0;
      if (this.dataDisplay) {
        let list = data.filter((ite) => !ite.type);
        let { width, minWidth } = data[data.length - 1];
        if (list.findIndex((ite) => !ite.width && !ite.minWidth) == -1) {
          delete data[data.length - 1].width;
          data[data.length - 1].minWidth = width || minWidth;
        }
        this.selfColumn = data;
        this.$nextTick(() => {
          this.doLayout();
        });
      }
    },
  },
  watch: {
    pageSize: {
      handler(val) {
        this.selfPageSize = val;
      },
      immediate: true,
    },
    formData: {
      handler(val) {
        this.queryParam = val;
      },
      immediate: true,
      deep: true,
    },
    maxHeight: {
      handler(val) {
        if (!val) return;
        this.selfMaxHeight = val;
      },
      immediate: true,
    },
    column: {
      handler(val) {
        if (!val) return;
        this.selfColumn = val;
      },
      immediate: true,
      deep: true,
    },
  },
};
</script>

<style lang="scss" scoped>
.operateList {
  // margin-bottom: 10px; //bing
}
.btn-pack {
  display: flex;
  flex-wrap: wrap;
}
.btn {
  margin-bottom: 10px;
}
.operateIcon {
  flex: 1;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  margin-right: 10px;
  i {
    font-size: 20px;
    margin-left: 15px;
    font-weight: 550;
    cursor: pointer;
    color: #333333;
  }
}
</style>
